const BASE_WIDTH = 800;
const BASE_HEIGHT = 600;
let scale = 1; // 缩放比例
function scaleVal(value) {
  return value * scale;
}

let cardGroup;
let targetCardGroup;
let unpositionedCardCount = 0;
let ifGenerating = false;
let mascot;
let mascotImg;
let answerText = "来试试看吧";
let bgImg = null;

let cardBg;
const mascotScale = 0.5; // 吉祥物缩放比例
const targetDefaultInterval = 120; // target默认间隔
const cardDefaultInterval = 120 * 0.8; // card默认间隔
const attachedDistance = 100;
const ttsClient = new VolcanoTTSClient();
let ifTTS = true;
let voiceMenu;

let cardImageMap = {
  targetImg: null, // target卡片背景
  cardBgImgNormal: null, // 通常卡片背景
  cardBgImgPress: null, // 通常卡片按下
  staticCardImgNormal: null, // 固定卡片背景
  staticCardImgPress: null, // 固定卡片按下
};

let defaultAudio = {
  click: null,
  correct: null,
  error: null,
  win: null,
};

let levelIndex = 0; // 当前是第几个关卡

let state = "game";

let levelInfo = [];

function updateLevelInfo(newCardInfo) {
  console.log("length of levelInfo", newCardInfo.length);
  levelInfo = newCardInfo;
  levelIndex = 0;
  unpositionedCardCount = 0;
  executeCardCode(levelInfo[levelIndex].cardCode);

  // 根据cardInfo修改sidebar
  const sidebarUl = document.querySelector("#mySidebar ul");
  sidebarUl.innerHTML = ""; // 清空现有列表

  levelInfo.forEach((info, index) => {
    const li = document.createElement("li");
    const a = document.createElement("a");
    a.textContent = info.description;
    // console.log("a", a);
    a.setAttribute("data-action", `card_${index}`);
    // 直接在这里添加点击事件
    a.addEventListener("click", (e) => {
      e.preventDefault();
      const action = a.getAttribute("data-action");
      window.sidebarInstance.emit("action", action);
      window.sidebarInstance.closeSidebar();
    });
    li.appendChild(a);
    sidebarUl.appendChild(li);
  });
}

async function fetchCardInfo() {
  // 定义 levelNames 数组
  const levelNames = [
    "2+2和4+2分别等于几？","6+2和8+2分别等于几？","10+2和12+2分别等于几？",
    "14+2和16+2分别等于几？","18+2和20+2分别等于几？","3+3和6+3等于几","9加3等于几啊？",
    "15加3等于几啊？","21加3和24加3等于几啊？","4加4和8+4等于几啊？","12加4等于几啊？",
    "20加4和24加4分别等于几？","5加5和10+5","15+5和20+5分别等于几","25+5和30+5分别等于几",
    "古诗诗句排序","9+2和9+7等于几","9+3和9+8等于几","","4和3加上几可以凑成10",
    "5-1等于4，所以5+9等于14","6-1等于5所以6+9等于15","7-1等于6所以7+9等于16",
    "8-2等于6所以8+8等于16","3-2等于1所以8+3等于11","4-2等于2所以4+8等于12",
    "5-2等于3所以5+8等于13","找规律填数 公差2 填3个","找规律填数 公差2 填2个","找规律填数 偶数 填2个",    
  ];
  console.log("开始获取卡片信息");
  try {
    // 调用新的后端接口
    const response = await fetch("http://106.54.192.233:8080/getLevelList", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        titles: levelNames, // 将 levelNames 传递给后端
      }),
    });

    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    } else {
      console.log("获取卡片信息成功");
    }

    // 解析返回的 JSON 数据
    const data = await response.json();

    // console.log("获取到的卡片信息:", data);

    // 提取返回的记录，并格式化为 cardInfo 的格式
    const formattedData = data.map((item) => ({
      description: item.title, // 使用 title 作为 description
      cardCode: JSON.parse(item.data), // 解析 data 字段并赋值给 cardCode
    }));

    // 因为sirly的后端这里没有按顺序返回，所以要重新排序
    // rerank formattedData with levelNames
    const levelNameToIndexMap = {};
    levelNames.forEach((name, index) => {
      levelNameToIndexMap[name] = index;
    });
    formattedData.sort(
      (a, b) =>
        levelNameToIndexMap[a.description] - levelNameToIndexMap[b.description]
    );

    updateLevelInfo(formattedData);

    // print length of formattedData
    console.log("卡片信息长度:", formattedData.length);
  } catch (error) {
    console.error("获取 cardInfo 数据时出错:", error);
  }
}

const cardInfoTemplate = {
  x: 100, // 横坐标
  y: 550, // 纵坐标
  draggable: true, // 是否可拖拽
  text: "窗前明月光", // 卡片上的文本
  textSize: 12, // 卡片上的文本大小
  width: 120 * 0.62, // 卡片的宽度
  height: 120, // 卡片的高度
  target: false, // 是否是答案框
  targetTrigger: function () {}, // 当target框被overlap时调用的函数
};

function preload() {
  // 吉祥物
  mascotImg = loadImage("./images/mascot.png");

  defaultAudio.click = loadSound("./audio/default_click.wav");
  defaultAudio.correct = loadSound("./audio/default_correct.wav");
  defaultAudio.error = loadSound("./audio/default_error.wav");
  defaultAudio.win = loadSound("./audio/default_win.wav");

  for (let key in defaultAudio) {
    defaultAudio[key].setVolume(1);
  }

  defaultAudio.win.setVolume(1.5);
  cardImageMap.targetImg = loadImage("./images/target.png");
  cardImageMap.cardBgImgNormal = loadImage("./images/card_nrm.png");
  cardImageMap.cardBgImgPress = loadImage("./images/card_prs.png");
  cardImageMap.staticCardImgNormal = loadImage("./images/scard_nrm.png");
  cardImageMap.staticCardImgPress = loadImage("./images/scard_prs.png");
}

function setup() {
  // 获取窗口大小并计算缩放比例
  const scaleX = windowWidth / BASE_WIDTH;
  const scaleY = windowHeight / BASE_HEIGHT;

  // 使用较小的缩放比例
  scale = Math.min(scaleX, scaleY);

  // 缩小一点保证不会溢出
  scale -= 0.02;

  // 计算实际canvas尺寸
  const canvasWidth = BASE_WIDTH * scale;
  const canvasHeight = BASE_HEIGHT * scale;

  createCanvas(canvasWidth, canvasHeight);

  // 更新sidebar的缩放比例
  window.sidebarInstance.updateScale();

  cardGroup = new Group();
  targetCardGroup = new Group();

  // 创建吉祥物
  mascot = createSprite(width / 5, scaleVal(50));
  mascot.addImage(mascotImg);
  mascot.scale = scaleVal(mascotScale);
  mascot.rotation = 180;
  mascot.collider = "none";

  const voiceSelect = document.getElementById("voiceSelect");
  voiceSelect.addEventListener("change", (event) => {
    const selectedVoice = event.target.value;
    if (selectedVoice === "none") {
      ifTTS = false;
      console.log("no voice");
    } else {
      ifTTS = true;
      //ttsClient.setVoice(selectedVoice);
    }
  });

  // 使用全局变量
  window.sidebarInstance.on("action", handleSidebarAction);

  fetchCardInfo();
}

function handleSidebarAction(action) {
  if (action.startsWith("card_")) {
    const index = parseInt(action.split("_")[1]);
    if (index >= 0 && index < levelInfo.length) {
      executeCardCode(levelInfo[index].cardCode);
    }
  }
}

// 鲁鲁 增加卡牌shuffle
function shuffleCards() {
  // 获取所有 draggable 为 true 的卡片
  const draggableCards = cardGroup.filter(
    (card) => card.draggable == true && !card.target && card.x > 0
  );

  // print all draggable cards
  // console.log("draggable cards: ", draggableCards);

  // 获取当前卡片的数量
  const cardCount = draggableCards.length;

  // 使用 Fisher-Yates 洗牌算法随机打乱卡片顺序
  for (let i = cardCount - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * cardCount);
    const temp = draggableCards[i].x;
    draggableCards[i].y -= scaleVal(200);
    draggableCards[i].x = draggableCards[j].x;
    draggableCards[j].x = temp;
    draggableCards[i].y += scaleVal(200);
  }
}

function executeCardCode(code) {
  // 重置状态
  cardGroup.removeAll();
  targetCardGroup.removeAll();
  unpositionedCardCount = 0;
  answerText = "来试试看吧";

  // 重置背景
  // TODO 读后端的背景图片
  // 读取bg文件夹下的所有文件
  let bgFiles = [];
  let bgPath = "./images/bg/";

  // 使用fetch获取文件列表
  fetch(bgPath)
    .then((response) => response.text())
    .then((data) => {
      // 解析HTML获取文件名
      let parser = new DOMParser();
      let doc = parser.parseFromString(data, "text/html");
      let files = doc.querySelectorAll("a");
      files.forEach((file) => {
        if (file.href.match(/\.(jpg|jpeg|png|gif)$/i)) {
          bgFiles.push(file.href);
        }
      });

      // 随机选择一个背景图
      if (bgFiles.length > 0) {
        let randomBg = random(bgFiles);
        loadImage(randomBg, (img) => {
          bgImg = img;
        });
      }
    })
    .catch((error) => {
      console.error("读取背景图片失败:", error);
    });

  // 分割代码行并移除空白行
  const lines = code
    .split("\n")
    .map((line) => line.trim())
    .filter((line) => line.length > 0);

  // 逐行执行代码
  lines.forEach((line, index) => {
    try {
      eval(line);
    } catch (error) {
      console.error(`第 ${index + 1} 行代码执行错误: ${line}`);
      console.error(error);
    }
  });

  shuffleCards();
}

// 定义函数调用 getImageList 接口
async function fetchImageURL(names) {
  const url = "http://106.54.192.233:8080/getImageList";
  const headers = {
    "Content-Type": "application/json",
  };

  const data = {
    names: names,
  };

  try {
    // 异步调用 fetch
    const response = await fetch(url, {
      method: "POST",
      headers: headers,
      body: JSON.stringify(data),
    });

    if (response.ok) {
      // 等待 JSON 数据解析
      const imageList = await response.json();
      return imageList;
    } else {
      console.error("获取图片列表失败，状态码: ", response.status);
      return {};
    }
  } catch (error) {
    console.error("调用 getImageList 接口时发生错误: ", error);
    return {};
  }
}

// 加载卡面
async function loadCardImage(card, finalCardInfo) {
  // 如果是第一次加载
  if (card.loadedImage == null) {
    // 如果是target
    if (finalCardInfo.target) {
      card.loadedImage = cardImageMap.targetImg;
    } else {
      // 如果存在文字对应的卡画
      const imageList = await fetchImageURL([finalCardInfo.text]);
      const imageURL = imageList[finalCardInfo.text];

      let url = "http://106.54.192.233/assets/" + imageURL;

      card.loadedImage = loadImage(url);
    }
  }
}

// 渲染卡面
function renderCardImage(card) {
  if (card.loadedImage != null && card.loadedImage != "failedToLoad") {
    // 图片以中心为锚点
    imageMode(CENTER);

    // 根据卡片状态选择背景图片
    const bgImage = card.draggable
      ? card.mouse.pressing()
        ? cardImageMap.cardBgImgPress
        : cardImageMap.cardBgImgNormal
      : card.mouse.pressing()
      ? cardImageMap.staticCardImgPress
      : cardImageMap.staticCardImgNormal;

    // 渲染卡片背景图片
    image(
      bgImage,
      card.position.x,
      card.position.y,
      card.width * 1.2,
      card.height * 1.2
    );

    // 渲染卡片内容图片
    const offsetY = card.mouse.pressing() && card.draggable ? 8 : 0;

    image(
      card.loadedImage,
      card.position.x,
      card.position.y + offsetY,
      card.width,
      card.height
    );
    // 复原图片锚点
    imageMode(CORNER);
  }
}

function rightAnswerHandler(card, overlappedTarget) {
  answerText = "答对了，真棒";
  if (overlappedTarget.correct_text !== undefined) {
    answerText = overlappedTarget.correct_text;
  }
  card.collider = "s";
  card.draggable = false;
  overlappedTarget.ifCorrect = true;
  defaultAudio.correct.play();
}

function wrongAnswerHandler(card, overlappedTarget) {
  answerText = "答错了，再想想";
  if (overlappedTarget.error_text !== undefined) {
    answerText = overlappedTarget.error_text;
  }
  overlappedTarget.ifCorrect = false;
  defaultAudio.error.play();
}

// 创建卡片
function createCard(cardInfo) {
  let finalCardInfo = Object.assign({}, cardInfoTemplate, cardInfo);

  let card = createSprite(
    finalCardInfo.x,
    finalCardInfo.y,
    finalCardInfo.width,
    finalCardInfo.height
  );

  card.draggable = finalCardInfo.draggable;
  if (!card.draggable) {
    card.collider = "s";
  }
  card.text = finalCardInfo.text;

  card.layer = finalCardInfo.target ? 1 : 99;
  if (finalCardInfo.answer !== undefined) {
    card.answer = finalCardInfo.answer;
  }
  card.targetTrigger = finalCardInfo.targetTrigger;
  card.correct_text = finalCardInfo.correct_text;
  card.error_text = finalCardInfo.error_text;

  let cardPressed = false;
  let overlappedTarget = null;

  card.loadedImage = null;
  loadCardImage(card, finalCardInfo);

  card.draw = () => {
    push();

    // 文本
    fill(0);
    textAlign(CENTER, CENTER);
    textSize(scaleVal(finalCardInfo.textSize));
    textWrap(CHAR);
    textStyle(NORMAL);
    text(finalCardInfo.text, 0, 0, finalCardInfo.width, finalCardInfo.height);
    pop();

    let overlapped = false;
    // overlap
    if (!finalCardInfo.target) {
      targetCardGroup.forEach((element) => {
        if (card.overlapping(element) > 0) {
          overlappedTarget = element;
          overlapped = true;
        }
      });
    }

    if (!overlapped) {
      overlappedTarget = null;
    }

    // 鼠标松开卡片时的事件
    if (card.mouse.pressing() === 0 && cardPressed) {
      if (!finalCardInfo.target && overlappedTarget) {
        // 吸附
        let far = dist(
          card.position.x,
          card.position.y,
          overlappedTarget.position.x,
          overlappedTarget.position.y
        );
        if (far < attachedDistance) {
          card.position.x = overlappedTarget.position.x;
          card.position.y = overlappedTarget.position.y;
          if (card.text === overlappedTarget.answer) {
            rightAnswerHandler(card, overlappedTarget);
          } else {
            wrongAnswerHandler(card, overlappedTarget);
          }
          overlappedTarget.targetTrigger();
        }
      }
    }

    if (card.mouse.pressing()) {
      cardPressed = true;
    } else {
      cardPressed = false;
    }

    if (ifTTS) {
      if (card.mouse.presses()) {
        ttsClient.requestTTS(card.text); /// should be clickedText in new levels
      }
    } else {
      if (card.mouse.pressed()) {
        defaultAudio.click.play();
      }
    }
  };

  card.update = () => {
    if (card.draggable && card.mouse.pressing()) {
      card.position.x = mouseX;
      card.position.y = mouseY;
    }

    renderCardImage(card);
  };

  if (finalCardInfo.target) {
    targetCardGroup.add(card);
  } else {
    cardGroup.add(card);
  }
}

function toggleWinModal() {
  const winModal = document.getElementById("winModal");
  const nextLevelBtn = document.getElementById("nextLevelBtn");
  const canvas = document.querySelector("canvas");
  const canvasRect = canvas.getBoundingClientRect();

  // 设置模态框的大小和位置与canvas一致
  winModal.style.position = "absolute";
  winModal.style.width = `${canvasRect.width}px`;
  winModal.style.height = `${canvasRect.height}px`;
  winModal.style.left = `${canvasRect.left}px`;
  winModal.style.top = `${canvasRect.top}px`;
  winModal.style.display = "flex";

  // 设置按钮大小
  const paddingV = scaleVal(15);
  const paddingH = scaleVal(40);
  const fontSize = scaleVal(24);

  nextLevelBtn.style.padding = `${paddingV}px ${paddingH}px`;
  nextLevelBtn.style.fontSize = `${fontSize}px`;
  nextLevelBtn.style.borderRadius = `${scaleVal(8)}px`;

  // 添加点击事件
  nextLevelBtn.addEventListener("click", () => {
    loop();
    cardGroup.removeAll();
    targetCardGroup.removeAll();
    answerText = "来试试看吧";
    state = "game";
    levelIndex = (levelIndex + 1) % levelInfo.length;
    executeCardCode(levelInfo[levelIndex].cardCode);
    winModal.style.display = "none";
  });
}

function draw() {
  clear();

  if (bgImg) {
    image(bgImg, 0, 0, width, height);
  }

  // 手牌分割线
  stroke(200);
  line(0, scaleVal(450), width, scaleVal(450));

  for (let card of cardGroup) {
    card.rotation = 0;
  }

  let correctCount = 0;
  for (let target of targetCardGroup) {
    target.rotation = 0;
    if (target.ifCorrect) {
      correctCount++;
    }
  }

  if (targetCardGroup.length === 0) {
    answerText = "请稍后，马上就好啦";
  }

  // 如果所有target都被正确回答
  if (
    state == "game" &&
    correctCount === targetCardGroup.length &&
    targetCardGroup.length > 0
  ) {
    answerText = "全部答对了，真棒！";
    defaultAudio.win.play();
    state = "win";
    correctCount = 0;
    unpositionedCardCount = 0;
    noLoop();

    toggleWinModal();
  }

  textSize(scaleVal(18));
  textAlign(LEFT);
  textStyle(BOLD);
  text(
    answerText,
    mascot.position.x + mascot.width / 2 + scaleVal(5),
    mascot.position.y + scaleVal(10)
  );
}

function set_meta(meta_info) {
  // 如果 start_audio 在 meta_info中，把answerText也设置为相同的值
  if (meta_info.start_audio) {
    answerText = meta_info.start_audio;
  }
}

function spawn_card(cardInfo) {
  let draggable = cardInfo.draggable !== undefined ? cardInfo.draggable : true;
  if (cardInfo.x !== undefined) {
    draggable = false;
  }
  let c = createCard({
    x:
      cardInfo.x !== undefined
        ? scaleVal(cardInfo.x)
        : scaleVal(cardDefaultInterval / 2) +
          unpositionedCardCount * scaleVal(cardDefaultInterval),
    y: cardInfo.y !== undefined ? scaleVal(cardInfo.y) : height - scaleVal(75),
    text: cardInfo.text,
    textSize: scaleVal(26),
    width: scaleVal(120) * 0.62,
    height: scaleVal(120),
    draggable: draggable,
  });

  if (cardInfo.x == undefined) {
    unpositionedCardCount++;
  }
}

function set_target(cardInfo) {
  let x = cardInfo.x !== undefined ? scaleVal(cardInfo.x) : -1;
  let y = cardInfo.y !== undefined ? scaleVal(cardInfo.y) : -1;
  let text = cardInfo.text !== undefined ? cardInfo.text : "?";

  if (x === -1 && y === -1) {
    // Default position to a candidate target area
    x = scaleVal(100) + unpositionedCardCount * scaleVal(targetDefaultInterval);
    y = height - scaleVal(150); // 确保target在上1/3区域
    unpositionedCardCount++;
  }

  let t = createCard({
    x: x,
    y: y,
    text: text,
    textSize: scaleVal(26),
    width: scaleVal(120) * 0.62,
    height: scaleVal(120),
    draggable: false,
    target: true,
    answer: cardInfo.answer,
    correct_text: cardInfo.correct_text,
    error_text: cardInfo.error_text,
  });
}
